(ns com.yawmark.barski.wiz)

(def *nodes* {
     :living-room '(you are in the living-room.
                        a wizard is snoring loudly on the couch.)
     :garden      '(you are in a beautiful garden.
                        there is a well in front of you.)
     :attic       '(you are in the attic.
                        there is a giant welding torch in the corner.)})

(def *edges* {
     :living-room  '((:garden west door)
                     (:attic upstairs ladder))
     :garden       '((:living-room east door)) 
     :attic        '((:living-room downstairs ladder))})
 
(def *object-locations* (ref '[[whiskey :living-room]
                               [bucket :living-room]
                               [chain :garden]
                               [frog :garden]]))

(def *location* (ref :living-room))

(defn describe-location [location nodes]
  (location nodes))

(defn describe-path [edge]
  (let [[_ direction passage] edge]
    (map #(symbol (name %))
         `(there is a ~passage going ~direction from here.))))

(defn describe-paths [location edges]
  (mapcat describe-path (location edges)))

(defn objects-at [loc obj-locs]
  (map first (filter #(= loc (second %)) obj-locs)))

(defn describe-object [obj]
  (map #(symbol (name %))
       `(you see a ~obj on the floor.)))

(defn describe-objects [loc obj-locs]
  (mapcat describe-object (objects-at loc obj-locs)))

(defn look []
  (concat (describe-location @*location* *nodes*)
          (describe-paths @*location* *edges*)
          (describe-objects @*location* @*object-locations*)))

(defn find-new-location [edges current-location direction]
  (some #(if (= (second %) direction) (first %) nil)
        (edges current-location)))

(defn walk [direction]
  (let [new-location (find-new-location *edges* @*location* direction)]
    (if new-location
      (dosync (ref-set *location* new-location)
              (look))
      '(you cannot go that way.))))


